﻿package we3d.scene 
{
	import we3d.View3d;
	import we3d.math.Matrix3d;
	import we3d.mesh.Vertex;
	import we3d.core.Camera3d;
	import we3d.scene.Bone;
	import we3d.scene.SceneObject;
	
	/** 
	* SceneObjectBones can transform their mesh with bones.
	*/
	public class SceneObjectBones extends SceneObject 
	{
		public function SceneObjectBones () {}
		
		/**
		* Array with all Bones of the object
		*/
		public var bones:Array;
		
		/**
		* Add a bone to the object
		*/
		public function addBone (b:Bone) :void {
			if(bones==null) bones = [];
			bones.push(b);
		}
		/**
		* @private
		*/
		public override function initFrame (f:Number, cam:Camera3d, cam_cgv:Matrix3d) :Boolean {
			if(super.initFrame(f, cam, cam_cgv)) return true;
			
			var L:int = bones.length;
			var b:Bone;
			for(var i:int=0; i<L; i++) {
				b = bones[i];
				if(b.frameInit) b.transform.initFrame(f);
			}
			return false;
		}
		/**
		* @private
		*/
		public override function initMesh (view:View3d, cgv:Matrix3d) :Boolean {
			
			var cam:Camera3d = view.scene.cam;
			
			super.initMesh(view, cgv);
			
			if(bones == null) {
				return false;
			}
			
			var v:Vertex;
			var bgv:Matrix3d;
			var bn:Bone;
			var _p:Array = points;
			var _bp:Array;
			
			var _bl:int = bones.length;
			var _w:Number = cam.t;	var _h:Number = cam.s;
			var x:Number;	var y:Number;	var z:Number;	var w1:Number;
			var restposx:Number;	var restposy:Number;	var restposz:Number;
			
			var gv:Matrix3d = transform.gv;
			
			var a:Number = gv.a;	var b:Number = gv.b;	var c:Number = gv.c;
			var e:Number = gv.e;	var f:Number = gv.f;	var g:Number = gv.g;
			var i:Number = gv.i;	var j:Number = gv.j;	var k:Number = gv.k;
			var m:Number = gv.m;	var n:Number = gv.n;	var o:Number = gv.o;
			var ptsL:int;
			var _j:int;
			var _i:int;
			
			var _l:int = bones.length;
			
			_l = _p.length;
			for( _i = 0; _i < _l; _i++) {
				v = _p[_i];
				
				v.wx = v.x;
				v.wy = v.y;
				v.wz = v.z;
			}
			
			for (_i=0; _i<_bl; _i++) {
				
				bn = bones[_i];
				
				restposx = bn.restPosition.x;	restposy = bn.restPosition.y;	restposz = bn.restPosition.z;
				_bp = bn.points;
				ptsL = _bp.length;
				bgv = bn.transform.gv;
				a = bgv.a;	b = bgv.b;	c = bgv.c;
				e = bgv.e;	f = bgv.f;	g = bgv.g;
				i = bgv.i;	j = bgv.j;	k = bgv.k;
				m = bgv.m;	n = bgv.n;	o = bgv.o;
				
				for(_j = 0; _j<ptsL; _j++) {
					v = _p[_bp[_j]];
					x = v.wx-restposx;	y = v.wy-restposy;	z = v.wz-restposz;
					v.wx = a*x + e*y + i*z + m;
					v.wy = b*x + f*y + j*z + n;
					v.wz = c*x + g*y + k*z + o;
				}
			}
			
			a = cgv.a;	b = cgv.b;	c = cgv.c;
			e = cgv.e;	f = cgv.f;	g = cgv.g;
			i = cgv.i;	j = cgv.j;	k = cgv.k;
			m = cgv.m;	n = cgv.n;	o = cgv.o + cam._nearClipping;
			
			for(_i=0; _i<_l; _i++) {
				
				v = _p[_i];
				v.frameCounter1 = v.frameCounter2 = frameCounter;
				
				x = v.wx;	y = v.wy; 	z = v.wz;
				
				v.wy = b*x + f*y + j*z + n;
				v.wx = a*x + e*y + i*z + m;
				w1 = c*x + g*y + k*z + o;
				v.wz = w1;
				
				if(w1!=0) {
					v.sy = _h - v.wy/w1 * _h;
					v.sx = _w + v.wx/w1 * _w;
				}else{
					v.sy = _h - v.wy * _h;
					v.sx = _w + v.wx * _w;
				}
			}
			
			return false;
		}
	
	}
}